/**
 * \file    symbol.cpp
 * \brief   Parser generator.
 * \author  Jérôme LAURENS
 * \version 0.1
 * \date    September 17, 2014
 *
 * Reads a LALR(1) grammar, generates a parser based on a template file.
 * This is based on lemon parser generator, but has strongly been
 * revisited.
 *
 */

#include "symbol.h"
#include "rule.h"
#include "grammar.h"
#include <assert.h>

LPP_NAMESPACE_BEGIN

/* Compare two symbols */
int compare(Symbol const & a, Symbol const & b) {
    if (a.name()<b.name()) return -1;
    if (a.name()>b.name()) return 1;
    return 0;
}
int compare(SymbolRef const & a, SymbolRef const & b) {
    return compare_Ref<SymbolRef>(a,b);
}
int compare(SymbolWRef const & a, SymbolWRef const & b) {
    return compare_WRef<SymbolWRef>(a,b);
}
int compare(SymbolRefList const & __lhs, SymbolRefList const & __rhs) {
    auto lhs_b = __lhs.begin();
    auto const lhs_e = __lhs.end();
    auto rhs_b = __rhs.begin();
    auto const rhs_e = __rhs.end();
    for (;lhs_b!=lhs_e && rhs_b!=rhs_e;++lhs_b,++rhs_b ) {
        if (!*lhs_b) {
            // DEBUG_MESSAGE("ERROR: %#lx,%#lx",reinterpret_cast<std::uintptr_t>(&lhs_b),reinterpret_cast<std::uintptr_t>(lhs_b->get()));
            auto b = __lhs.begin();
            auto e = __lhs.end();
            for (;b!=e;++b) {
                std::cout<<*b<<std::endl;
            }
        }
        if (!*rhs_b) {
            // DEBUG_MESSAGE("ERROR: %#lx,%#lx",reinterpret_cast<std::uintptr_t>(&rhs_b),reinterpret_cast<std::uintptr_t>(rhs_b->get()));
            auto b = __rhs.begin();
            auto e = __rhs.end();
            for (;b!=e;++b) {
                std::cout<<*b<<std::endl;
            }
        }
        int i = compare(*lhs_b,*rhs_b);
        if (i) return  i;
    }
    if (rhs_b!=rhs_e) return -1;
    if (lhs_b!=lhs_e) return  1;
    return 0;
}


bool operator==(const Symbol& a, const Symbol& b) {
    return compare(a,b)==0;
}
bool operator==(SymbolRef const & a, SymbolRef const & b) {
    return compare(a,b)==0;
}
bool operator==(SymbolWRef const & a, SymbolWRef const & b) {
    return compare(a,b)==0;
}
bool operator<(SymbolWRef const & a, SymbolWRef const & b) {
    return compare(a,b)<0;
}
bool operator<(SymbolRef const & a, SymbolRef const & b) {
    return compare(a,b)<0;
}
bool operator<(Symbol const & a, Symbol const & b) {
    return compare(a,b)<0;
}
bool Symbol::promote_to_multi_terminal() {
    if (grammar_m.promote_to_multi_terminal(this->name_m)) {
        type_m = Type::MULTITERMINAL;
    }
    return is_multi_terminal();
}

bool Symbol::promote_to_default() {
    if (grammar_m.promote_to_default(this->name_m)) {
        type_m = Type::DEFAULT;
    }
    return is_default();
}

LPP_NAMESPACE_END
